package com.lichi.zabbix.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.lichi.zabbix.auth.UserDO;
import com.lichi.zabbix.entity.ZabbixHost;
import com.lichi.zabbix.entity.ZabbixRequest;
import com.lichi.zabbix.entity.ZabbixRequestBuilder;
import com.lichi.zabbix.entity.ZabbixTemplateVO;
import com.lichi.zabbix.response.*;
import com.lichi.zabbix.server.ServerDO;
import com.lichi.zabbix.service.ZabbixService;
import com.lichi.zabbix.util.BusinessWrapper;
import com.lichi.zabbix.util.ErrorCode;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author lichi
 * @create 2020-05-27 14:49
 */
@Service
@PropertySource("classpath:application.yml")
@ConfigurationProperties(prefix = "zabbix")
public class ZabbixServiceImpl implements ZabbixService {

    private static final Logger logger = LoggerFactory.getLogger(ZabbixServiceImpl.class);

    @Value("${url}")
    private String zabbixUrl;

    @Value("${user}")
    private String zabbixUser;

    @Value("${passwd}")
    private String zabbixPasswd;

    public static final String ZABBIX_KEY_RESULT = "result";

    public static final String ZABBIX_KEY_APIINFO = "apiinfo.version";

    private URI uri;

    private volatile String auth;

    private CloseableHttpClient httpClient;

    @Override
    public void init() {
        if (StringUtils.isEmpty(zabbixUrl)) {
            return;
        }
        logger.info("Zabbix初始化 : {}", zabbixUrl);
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5 * 1000).setConnectionRequestTimeout(5 * 1000).setSocketTimeout(5 * 1000).build();
        PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
        CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(connManager).setDefaultRequestConfig(requestConfig).build();
        setUrl(zabbixUrl);
        setHttpClient(httpclient);
        login();
    }

    private void setUrl(String url) {
        try {
            uri = new URI(url.trim());
        } catch (URISyntaxException e) {
            throw new RuntimeException("zabbix url invalid", e);
        }
    }

    private void setHttpClient(CloseableHttpClient httpClient) {
        this.httpClient = httpClient;
    }

    /**
     * zabbix登录验证是否成功
     * @return
     */
    public boolean login() {
        if (StringUtils.isEmpty(zabbixUrl)) {
            return false;
        }
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder().paramEntry("user", zabbixUser).paramEntry("password", zabbixPasswd).method("user.login").build();
        try {
            HttpUriRequest httpRequest = org.apache.http.client.methods.RequestBuilder.post().setUri(uri).addHeader("Content-Type", "application/json").setEntity(new StringEntity(JSON.toJSONString(request), ContentType.APPLICATION_JSON)).build();
            CloseableHttpResponse response = httpClient.execute(httpRequest);
            HttpEntity entity = response.getEntity();
            byte[] data = EntityUtils.toByteArray(entity);
            Gson gson = new GsonBuilder().create();
            ZabbixResponseUserLogin userLogin = gson.fromJson(JSON.parse(data).toString(), ZabbixResponseUserLogin.class);
            if (!StringUtils.isEmpty(userLogin.getAuth())) {
                logger.info("Zabbix登录成功 !");
                this.auth = userLogin.getAuth();
                logger.info("返回的token值："+this.auth);
                return true;
            }
        } catch (IOException e) {
            logger.error("zabbix登录失败!");
        }
        return false;
    }

    /**
     * zabbix获取版本号
     * @return
     */
    @Override
    public String getApiVersion() {
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder().method("apiinfo.version").build();
        JSONObject response = call(request);
        return response.getString("result");
    }

    @Override
    public ZabbixResponseHost getHost(String hostid) {
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder().method("host.get").build();
        request.putParam("hostids", hostid);
        try {
            JSONObject response = call(request);
            Gson gson = new GsonBuilder().create();
            List<ZabbixResponseHost> hostList = gson.fromJson(response.getJSONArray(ZABBIX_KEY_RESULT).toString(), new TypeToken<ArrayList<ZabbixResponseHost>>() {
            }.getType());
            for (ZabbixResponseHost host : hostList){
                return host;
            }
        } catch (Exception e) {
            logger.info("Zabbix查询主机失败！");
        }
        return new ZabbixResponseHost();
    }

    /**
     * zabbix接口调度公共方法
     * @param request
     * @return
     */
    private JSONObject call(ZabbixRequest request) {
        if (request.getAuth() == null && !request.getMethod().equalsIgnoreCase(ZABBIX_KEY_APIINFO) && !"user.login".equalsIgnoreCase(request.getMethod())) {
            if (StringUtils.isEmpty(auth)) {
                return null;
            }
            request.setAuth(auth);
        }
        try {
            HttpUriRequest httpRequest = org.apache.http.client.methods.RequestBuilder.post().setUri(uri).addHeader("Content-Type", "application/json").setEntity(new StringEntity(JSON.toJSONString(request), ContentType.APPLICATION_JSON)).build();
            CloseableHttpResponse response = httpClient.execute(httpRequest);
            HttpEntity entity = response.getEntity();
            byte[] data = EntityUtils.toByteArray(entity);
            JSONObject jsonObject = JSONObject.parseObject(JSON.parse(data).toString());
            return jsonObject;
        } catch (IOException e) {
            logger.error("Zabbix接口错误!");
        }
        return null;
    }

    /**
     * zabbix创建用户
     * @param userDO 用户实体类
     * @return
     */
    @Override
    public BusinessWrapper<Boolean> createUser(UserDO userDO) {
        if (userDO == null) {
            return new BusinessWrapper<>(ErrorCode.userNotExist.getCode(), ErrorCode.userNotExist.getMsg());
        }
        if (userDO.getZabbixAuthed() == UserDO.ZabbixAuthType.authed.getCode()) {
            return new BusinessWrapper<Boolean>(true);
        }
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder().method("user.create").build();
        request.putParam("alias", userDO.getUsername());
        request.putParam("name", userDO.getDisplayName());
        request.putParam("passwd", userDO.getPwd());
        request.putParam("usrgrps", acqUsergrps());
        JSONArray userMedias = new JSONArray();
        userMedias.add(acqUserMedias(1, userDO.getMail()));
        if (userDO.getMobile() != null && !userDO.getMobile().isEmpty()) {
            userMedias.add(acqUserMedias(3, userDO.getMobile()));
        }
        request.putParam("user_medias", userMedias);
        try {
            JSONObject response = call(request);
            String result = response.getJSONObject(ZABBIX_KEY_RESULT).getJSONArray("userids").toJSONString();
            Gson gson = new GsonBuilder().create();
            List<String> usrgrpids = gson.fromJson(result, new TypeToken<ArrayList<String>>() {}.getType());
            String userid = usrgrpids.get(0);
            System.out.println("添加用户返回的值："+userid);
            if (!StringUtils.isEmpty(userid)) {
                return new BusinessWrapper<>(true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new BusinessWrapper<>(ErrorCode.zabbixUserCreate.getCode(), ErrorCode.zabbixUserCreate.getMsg());
    }

    private JSONArray acqUsergrps() {
        JSONArray groups = new JSONArray();
        JSONObject defaultUsergrp = new JSONObject();
        defaultUsergrp.put("usrgrpid", "7");
        groups.add(defaultUsergrp);
        System.err.println(groups);
        return groups;
    }

    private JSONObject acqUserMedias(int mediatypeid, String sendto) {
        if (sendto == null) {
            return null;
        }
        JSONObject medias = new JSONObject();
        medias.put("mediatypeid", mediatypeid);
        medias.put("sendto", sendto);
        medias.put("active", 0);
        medias.put("severity", 48);
        medias.put("period", "1-7,00:00-24:00");
        return medias;
    }

    /**
     * zabbix获取用户所在的用户组
     * @param usergroup
     * @return
     */
    @Override
    public ZabbixResponseUsergroup getUsergroup(String usergroup) {
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder().method("usergroup.get").build();
        request.putParam("status", 0);
        if (usergroup != null) {
            JSONObject filter = new JSONObject();
            filter.put("name", usergroup);
            request.putParam("filter", filter);
        }
        JSONObject response = call(request);
        String result = response.getJSONArray(ZABBIX_KEY_RESULT).toJSONString();
        try {
            Gson gson = new GsonBuilder().create();
            List<ZabbixResponseUsergroup> usergroupList = gson.fromJson(result, new TypeToken<ArrayList<ZabbixResponseUsergroup>>() {}.getType());
            return usergroupList.get(0);
        } catch (Exception e) {
        }
        return new ZabbixResponseUsergroup();
    }

    /**
     * zabbix创建主机组
     * @param hostgroupName
     * @return
     */
    @Override
    public String createHostgroup(String hostgroupName) {
        ZabbixResponseHostgroup hostgroup = getHostgroup(hostgroupName);
        if (hostgroup != null && !StringUtils.isEmpty(hostgroup.getGroupid())) {
            return hostgroup.getGroupid();
        }
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder().method("hostgroup.create").paramEntry("name", hostgroupName).build();
        JSONObject response = call(request);
        try {
            String result = response.getJSONObject(ZABBIX_KEY_RESULT).getJSONArray("groupids").toJSONString();
            Gson gson = new GsonBuilder().create();
            List<String> groupids = gson.fromJson(result, new TypeToken<ArrayList<String>>() {
            }.getType());
            return groupids.get(0);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * zabbix获取主机组
     * @param name
     * @return
     */
    @Override
    public ZabbixResponseHostgroup getHostgroup(String name) {
        JSONObject filter = new JSONObject();
        filter.put("name", name);
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder().method("hostgroup.get").paramEntry("filter", filter).paramEntry("output", "extend").build();
        JSONObject response = call(request);
        try {
            String result = response.getJSONArray(ZABBIX_KEY_RESULT).toJSONString();
            Gson gson = new GsonBuilder().create();
            List<ZabbixResponseHostgroup> hostgroupList = gson.fromJson(result, new TypeToken<ArrayList<ZabbixResponseHostgroup>>() {}.getType());
            return hostgroupList.get(0);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * zabbix获取主机模板
     * @return
     */
    @Override
    public List<ZabbixResponseTemplate> queryTemplates() {
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder().method("template.get").build();
        JSONObject response = call(request);
        String result = response.getJSONArray(ZABBIX_KEY_RESULT).toJSONString();
        Gson gson = new GsonBuilder().create();
        List<ZabbixResponseTemplate> templateList = gson.fromJson(result, new TypeToken<ArrayList<ZabbixResponseTemplate>>() {}.getType());
        return templateList;
    }

    /**
     * zabbix根据模板名称获取主机模板
     * @param name 模板名称
     * @return
     */
    @Override
    public ZabbixResponseTemplate getTemplate(String name) {
        JSONObject filter = new JSONObject();
        filter.put("name", name);
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder().method("template.get").paramEntry("filter", filter).build();
        JSONObject response = call(request);
        String result = response.getJSONArray(ZABBIX_KEY_RESULT).toJSONString();
        Gson gson = new GsonBuilder().create();
        List<ZabbixResponseTemplate> templateList = gson.fromJson(result, new TypeToken<ArrayList<ZabbixResponseTemplate>>() {}.getType());
        return templateList.get(0);
    }


    /**
     * zabbix创建主机
     * @return
     */
    @Override
    public boolean createHost(String name) {
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder().method("host.create").build();
        request.putParam("host", "192.168.130.88");
        request.putParam("interfaces", acqInterfaces());
        request.putParam("groups", acqGroup());
        request.putParam("templates", acqTemplate());
        try {
            JSONObject response = call(request);
            String result = response.getJSONObject(ZABBIX_KEY_RESULT).getJSONArray("hostids").toJSONString();
            Gson gson = new GsonBuilder().create();
            List<String> hostids = gson.fromJson(result, new TypeToken<ArrayList<String>>() {}.getType());
            String hostid = hostids.get(0);
            if (!StringUtils.isEmpty(hostid)) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    private JSONArray acqInterfaces() {
        JSONArray interfaces = new JSONArray();
        interfaces.add(buildInterfaces("192.168.130.88", 1, "10050"));
        return interfaces;
    }

    private JSONObject buildInterfaces(String ip, int type, String port) {
        JSONObject zabbixIf = new JSONObject();
        zabbixIf.put("type", type);
        zabbixIf.put("main", 1);
        zabbixIf.put("useip", 1);
        zabbixIf.put("ip", ip);
        zabbixIf.put("dns", "");
        zabbixIf.put("port", port);
        return zabbixIf;
    }


    private JSONArray acqTemplate() {
        JSONArray templateArray = new JSONArray();
        JSONObject template = new JSONObject();
        template.put("templateid", "10327");
        templateArray.add(template);
        return templateArray;
    }

    private JSONArray acqGroup() {
        JSONArray jsonarray = new JSONArray();
        JSONObject jsonobject = new JSONObject();
        jsonobject.put("groupid", "18");
        jsonarray.add(jsonobject);
        return jsonarray;
    }

    public JSONObject getHistory() {
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder()
                .method("history.get").build();
        request.putParam("history", 4);//0 - numeric float;数字浮点数 1 - character;字符 2 - log; 日志 3 - numeric unsigned; 数字符号 4 - text.文本
        request.putParam("itemids", "10316");
        request.putParam("sortfield", "clock");
        request.putParam("sortorder", "DESC");
        request.putParam("limit", 10);
        return call(request);
    }

    /**
     * zabbix 根据主机号获取监控项
     * @param hostId
     * @return
     */
    @Override
    public List<ZabbixResponseItem> queryItems(String hostId) {
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder()
                .method("item.get").build();
        request.putParam("output", "extend");
        request.putParam("hostids", "10316");
        request.putParam("sortfield", "name");
        try {
            JSONObject response = call(request);
            String result = response.getJSONArray(ZABBIX_KEY_RESULT).toJSONString();
            Gson gson = new GsonBuilder().create();
            List<ZabbixResponseItem> itemList = gson.fromJson(result, new TypeToken<ArrayList<ZabbixResponseItem>>() {}.getType());
            return itemList;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList<ZabbixResponseItem>();
    }

    @Override
    public List<ZabbixResponseHost> getHost() {
        ZabbixRequest request = ZabbixRequestBuilder.newBuilder().method("host.get").build();
        try {
            JSONObject response = call(request);
            Gson gson = new GsonBuilder().create();
            List<ZabbixResponseHost> hostList = gson.fromJson(response.getJSONArray(ZABBIX_KEY_RESULT).toString(), new TypeToken<ArrayList<ZabbixResponseHost>>() {}.getType());
            return hostList;
        } catch (Exception e) {
            logger.info("Zabbix查询主机失败！");
        }
        return null;
    }

}
